package com.ease.model.criterion;

import java.util.Collection;

import com.ease.common.util.Assertion;
import com.ease.common.util.Detect;

/**
 * 
 * @author nathanleewei
 * 
 */
public abstract class CriteriaBuilder extends Detect {

	private QueryCriteria queryCriteria;

	public abstract void buildQueryCriteria();

	public QueryCriteria toQueryCriteria() {
		buildQueryCriteria();
		return getQueryCriteria();
	}

	private QueryCriteria getQueryCriteria() {
		if (null == queryCriteria)
			queryCriteria = new QueryCriteria();
		return queryCriteria;
	}

	public Criterion and(Criterion... criteria) {
		Assertion.notNull(criteria, "criteria must be not null");
		Assertion.isTrue(criteria.length > 0, "criteria must be not null");

		Conjunction conjuntion = Restrictions.conjunction();

		for (int i = 0; i < criteria.length; i++) {
			conjuntion.add(criteria[i]);
		}
		this.getQueryCriteria().add(conjuntion);
		return conjuntion;
	}

	public Criterion or(Criterion... criteria) {

		Assertion.notNull(criteria, "criteria must be not null");
		Assertion.isTrue(criteria.length > 0, "criteria must be not null");

		Disjunction disjunction = Restrictions.disjunction();

		for (int i = 0; i < criteria.length; i++) {
			disjunction.add(criteria[i]);
		}
		this.getQueryCriteria().add(disjunction);
		return disjunction;
	}

	public Criterion eq(String propertyName, Object value) {
		Criterion criterion = Restrictions.eq(propertyName, value);
		return criterion;
	}

	public Criterion like(String propertyName, String value) {
		Criterion criterion = Restrictions.like(propertyName, value);
		return criterion;
	}

	/**
	 * Apply a "greater than" constraint to the named property
	 * 
	 * @param propertyName
	 * @param value
	 * @return Criterion
	 */
	public static Criterion gt(String propertyName, Object value) {
		Criterion criterion = Restrictions.gt(propertyName, value);
		return criterion;
	}

	/**
	 * Apply a "less than" constraint to the named property
	 * 
	 * @param propertyName
	 * @param value
	 * @return Criterion
	 */
	public static Criterion lt(String propertyName, Object value) {
		Criterion criterion = Restrictions.lt(propertyName, value);
		return criterion;
	}

	/**
	 * Apply a "less than or equal" constraint to the named property
	 * 
	 * @param propertyName
	 * @param value
	 * @return Criterion
	 */
	public static Criterion le(String propertyName, Object value) {
		Criterion criterion = Restrictions.le(propertyName, value);
		return criterion;
	}

	/**
	 * Apply a "greater than or equal" constraint to the named property
	 * 
	 * @param propertyName
	 * @param value
	 * @return Criterion
	 */
	public static Criterion ge(String propertyName, Object value) {
		Criterion criterion = Restrictions.ge(propertyName, value);
		return criterion;
	}

	/**
	 * Apply a "between" constraint to the named property
	 * 
	 * @param propertyName
	 * @param lo
	 *            value
	 * @param hi
	 *            value
	 * @return Criterion
	 */
	public static Criterion between(String propertyName, Object lo, Object hi) {
		Criterion criterion = Restrictions.between(propertyName, lo, hi);
		return criterion;
	}

	/**
	 * Apply an "in" constraint to the named property
	 * 
	 * @param propertyName
	 * @param values
	 * @return Criterion
	 */
	public static Criterion in(String propertyName, Object[] values) {
		Criterion criterion = Restrictions.in(propertyName, values);
		return criterion;
	}

	/**
	 * Apply an "in" constraint to the named property
	 * 
	 * @param propertyName
	 * @param values
	 * @return Criterion
	 */
	public static Criterion in(String propertyName, Collection<?> values) {
		Criterion criterion = Restrictions.in(propertyName, values);
		return criterion;
	}

	/**
	 * Apply an "is null" constraint to the named property
	 * 
	 * @return Criterion
	 */
	public static Criterion isNull(String propertyName) {
		Criterion criterion = Restrictions.isNull(propertyName);
		return criterion;
	}

	/**
	 * Apply an "is not null" constraint to the named property
	 * 
	 * @return Criterion
	 */
	public static Criterion isNotNull(String propertyName) {
		Criterion criterion = Restrictions.isNotNull(propertyName);
		return criterion;
	}

}
